# 线性筛，保证每个合数只被最小质因数筛去
# 时间复杂度为 O（n）因为一个数，只被筛了一次

def get_prime(n):
    # vis 表示是否已标记
    vis=[0]*(n+1)
    # prime 存储所有素数
    prime=[]
    # 从 2--n 遍历所有数字，找到第一个未标记的数字，即为素数
    for i in range(2,n):
        if vis[i]==0:
            prime.append(i)
        # 遍历素数列表
        for x in prime:
            # 范围超过n，不需要标记，结束
            if i*x > n:
                break
            # 对i*x 进行标记，因为他不可能是质数
            vis[i*x]=1
            # i能整除x，意味着 x 是 i 的最小质因数。此时，算法会跳出内层循环，不再继续用 prime 列表中更大的素数去标记 i 的倍数
            # 原因：避免重复标记
            # 假设当前 i 能被 x 整除，即 i = k * x（k 为整数）。如果继续用 prime 列表中比 x 更大的素数 y 去标记 i * y，也就是 (k * x) * y，
            # 那么 i * y 这个合数就会在后续当 i' = k * y 时，再次被 x 标记（因为 i' * x = (k * y) * x = i * y），这就造成了重复标记，会增加不必要的计算量。
            if i%x==0:
                break
    return prime

n=int(input())
a=get_prime(n)
print(*a)
print(len(a))